<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta http-equiv="X-UA-Compatible" content="IE=edge">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Array</title>
</head>
<body>
  <script>
    // 1. 创建数组
    // 创建空数组
    let array0 = new Array();
    console.log(array0);
    // 创建含有能添加length为3个元素数组
    let array1 = new Array(3);
    console.log(array1);
    // 创建含有默认元素的数组
    let array2 = new Array("aaa", "bbb", "ccc");
    console.log(array2);
    console.log(array2);

    // 数组字面量
    let array3 = [];
    let array4 = [1, 3, 5];
    let array5 = ["read", "green"];
    console.log(array3, array4, array5);
    // Array.from()的第一个参数是一个类数组对象，即任何可迭代的结构，或者有一个 length 属性和可索引元素的结构
    let array6 = Array.from("materials");
    console.log(array6);

    const a1 = [1, 2, 3, 4];
    const a2 = Array.from(a1, x => x ** 2);
    const a3 = Array.from(a1, function (x) {
       return x ** this.exponent 
      }, { exponent: 2 });
    console.log(a2); // [1, 4, 9, 16]
    console.log(a3); // [1, 4, 9, 16]

    // Array.of()可以把一组参数转换为数组。这个方法用于替代在 ES6 之前常用的 Array.prototype.slice.call(arguments)一种异常笨拙的将 arguments 对象转换为数组的写法：
    console.log(Array.of(1, 2, 3, 4)); // [1, 2, 3, 4]
    console.log(Array.of(undefined)); // [undefined]

    // 填充数组 copyWithin() 和 fill() 属性方法
    let zeroes = [0, 0, 0, 0, 0];
    console.log(zeroes);
    // 用4填充所有元素
    zeroes.fill(4);
    console.log(zeroes);
    // 用5填充索引大于等于2的所有元素
    zeroes.fill(5, 2);
    console.log(zeroes);
    // 用8 替换索引为大于等于1小于4的元素
    zeroes.fill(8, 1, 4);
    console.log(zeroes);
    // 用 8 填充索引大于等于 1 且小于 4 的元素
    // (-4 + zeroes.length = 1)
    // (-1 + zeroes.length = 4)
    zeroes.fill(8, -4, -1);

      // 索引过低，忽略
      zeroes.fill(1, -10, -6);
      console.log(zeroes); // [0, 0, 0, 0, 0]
      // 索引过高，忽略
      zeroes.fill(1, 10, 15);
      console.log(zeroes); // [0, 0, 0, 0, 0]
      // 索引反向，忽略
      zeroes.fill(2, 4, 2);
      console.log(zeroes); // [0, 0, 0, 0, 0]
      // 索引部分可用，填充可用部分
      zeroes.fill(4, 3, 10)
      console.log(zeroes); // [0, 0, 0, 4, 4]
    
      // copyWithin()会按照指定范围浅复制数组中的部分内容
      let ints;
      let reset = () => ints = [1, 3, 5, 7, 9, 11, 13, 15];
      reset();
      // 从 ints 中复制索引 0 开始的内容，插入到索引 5 开始的位置
      // 在源索引或目标索引到达数组边界时停止
      ints.copyWithin(5);
      console.log(ints);

      reset();
      ints.copyWithin(1, 5); // [ 1, 11, 13, 15, 9, 11, 13, 15 ]
      console.log(ints);

      // 从 ints 中复制索引 0 开始到索引 3 结束的内容
      // 插入到索引 4 开始的位置
      reset();
      ints.copyWithin(4, 0, 3);
      console.log(ints);  // [ 1, 3, 5, 7, 1, 3, 5, 15 ]

      // 转化
      // 转化为,分隔的字符串
      console.log(ints.toString()); // "1,3,5,7,1,3,5,15"
      console.log(ints.valueOf());

      // join 使用其他分隔符拼接
      console.log(ints.join("*")); // "1*3*5*7*1*3*5*15"

      // 栈方法
      let names = [];
      let count1 = names.push("hello"); // 返回当数组元素个数
      console.log(count1);
      let count2 = names.push("world", "vue");
      console.log(count2);
      console.log(names); //["hello", "world", "vue"]

      let lastItem = names.pop();
      console.log(lastItem);
      console.log(names);
      
      // 队列方法
      let firstItem = names.shift(); // 取出第一项(删除数组第一个恶元素)
      console.log(firstItem);
      console.log(names);

      names.unshift("Hi"); // 向数组第一项插入元素
      console.log(names);

      // 排序方法
      // 数组有两个方法可以用来对元素重新排序： reverse()和 sort() 。顾名思义， reverse()方法就
      // 是将数组元素反向排列。比如：
        
      let values = [1, 2, 3, 4, 5];
      values.reverse();
      console.log(values);
      values.sort();
      console.log(values);
      
      ints.sort((s1, s2) => s1 > s2);
      console.log(ints);

      // 操作方法
      // concat()方法可以在现有数组全部元素基础上
      // 创建一个新数组。它首先会创建一个当前数组的副本，然后再把它的参数添加到副本末尾，最后返回这
      // 个新构建的数组。如果传入一个或多个数组，则 concat()会把这些数组的每一项都添加到结果数组。
      // 如果参数不是数组，则直接把它们添加到结果数组末尾。来看下面的例子：
        let colors = ["red", "green", "blue"];
        let colors2 = colors.concat("yellow", ["black", "brown"]);
        console.log(colors); // ["red", "green","blue"]
        console.log(colors2); // ["red", "green", "blue", "yellow", "black", "brown"]
      
        // slice 
        
        // 元素切片, 子数组获取
        console.log(ints.slice(2)); // 从索引为2的元素开始和之后的所有元素
 
        console.log(ints.slice(1, 3)); // 从索引为1的元素到索引为三的元素之的元素

        // splice
        // 删除或添加元素
        // 删除:
        // 需要给 splice()传 2 个参数：要删除的第一个元素的位置和要删除的元素数量。可以从数组中删除任意多个元素，比如 splice(0, 2)会删除前两个元素。
        // 插入:
        // 需要给 splice()传 3 个参数：开始位置、 0（要删除的元素数量）和要插入的元素，可以在数组中指定的位置插入元素。第三个参数之后还可以传第四个、第五个参数，乃至任意多个要插入的元素。比如， splice(2, 0, "red", "green")会从数组位置 2 开始插入字符串"red"和"green"。
        // 替换:
        // splice()在删除元素的同时可以在指定位置插入新元素，同样要传入 3 个参数：开始位置、要删除元素的数量和要插入的任意多个元素。要插入的元素数量不一定跟删除的元素数量一致。比如， splice(2, 1, "red", "green")会在位置 2 删除一个元素，然后从该位置开始向数组中插入"red"和"green"。
        let colors = ["red", "green", "blue"];
        let removed = colors.splice(0, 1); // 删除第一项
        console.log(colors); // green,blue
        console.log(removed); // red，只有一个元素的数组
        removed = colors.splice(1, 0, "yellow", "orange"); // 在位置 1 插入两个元素
        console.log(colors); // green,yellow,orange,blue
        console.log(removed); // 空数组
        removed = colors.splice(1, 1, "red", "purple"); // 插入两个值，删除一个元素
        console.log(colors); // green,red,purple,orange,blue
        console.log(removed); // yellow，只有一个元素的数组


  </script>
</body>
</html>